package com.erp.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.util.CollectionUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.*;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

@Slf4j
public class HttpClient {

    private static boolean isCert = false;

    private static String HTTPS_TYPE = "https";

    private static RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(60000).setSocketTimeout(60000).setConnectionRequestTimeout(60000).build();
    private static X509TrustManager tm = new X509TrustManager() {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };

    public static String postFormData(String url, InputStream inputStream, String filename, Map<String, String> header, Map<String, String> data) {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        if (url.startsWith(HTTPS_TYPE)) {
            try {
                httpclient = getHttpsClient();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            HttpPost httpPost = new HttpPost(url);
            if (null != header) {
                header.forEach(httpPost::addHeader);
            }
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(200000).setSocketTimeout(200000).build();
            httpPost.setConfig(requestConfig);
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            // 添加文件
            if (null != inputStream && StringUtils.isNotBlank(filename)) {
                builder.addBinaryBody("file", inputStream, ContentType.APPLICATION_OCTET_STREAM, filename);
            }
            // 添加非文件
            data.forEach((name, values) -> builder.addTextBody(name, values, ContentType.MULTIPART_FORM_DATA));
            HttpEntity httpEntity = builder.build();
            httpPost.setEntity(httpEntity);
            CloseableHttpResponse response = httpclient.execute(httpPost);
            try {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    return EntityUtils.toString(response.getEntity());
                }
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static String httpPost(String url, Map<String, Object> data, Map<String, String> header) {
        StringBuffer sb = new StringBuffer();
        // 创建HttpClient实例
        @SuppressWarnings({"resource", "deprecation"})
        org.apache.http.client.HttpClient httpclient = HttpClients.createDefault();
        if (url.startsWith(HTTPS_TYPE)) {
            try {
                httpclient = getHttpsClient();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 创建Get方法实例
        HttpPost httpPost = new HttpPost(url);
        if (null != header) {
            header.forEach(httpPost::addHeader);
        }
        try {
            if (data != null) {
                //模拟form进行表单提交,也可以是别的比如StringEntity
                httpPost.setEntity(new StringEntity(JSONObject.toJSONString(data), ContentType.create(ContentType.APPLICATION_JSON.getMimeType(), "UTF-8")));
            }
            httpPost.setConfig(requestConfig);
            HttpResponse response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream inputStream = entity.getContent();
                // post result
                InputStreamReader ip = new InputStreamReader(inputStream);
                BufferedReader reader = new BufferedReader(ip);
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
                reader.close();
            }
        } catch (ClientProtocolException e) {
            httpPost.abort();//断开终止连接
            e.printStackTrace();
        } catch (IOException e) {
            httpPost.abort();
            e.printStackTrace();
        } finally {
            httpPost.releaseConnection();//释放连接到连接池
            httpclient.getConnectionManager().shutdown();//关闭httpclient
        }
        return sb.toString();
    }

    public static String httpGet(String URL, Map<String, String> params, Map<String, String> header) {
        StringBuffer sb = new StringBuffer();
        // 创建HttpClient实例
        @SuppressWarnings({"resource", "deprecation"})
        org.apache.http.client.HttpClient httpclient = HttpClients.createDefault();
        if (URL.startsWith(HTTPS_TYPE)) {
            try {
                httpclient = getHttpsClient();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 创建Get方法实例
        if (!CollectionUtils.isEmpty(params)) {
            URL = getUrlWithQueryString(URL, params);
        }
        HttpGet httpGet = new HttpGet(URL);
        if (null != header) {
            header.forEach(httpGet::addHeader);
        }
        try {
            HttpResponse response = httpclient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream inputStream = entity.getContent();
                // post result
                InputStreamReader ip = new InputStreamReader(inputStream);
                BufferedReader reader = new BufferedReader(ip);
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
                reader.close();
                httpGet.abort();
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    public static String getUrlWithQueryString(String url, Map<String, String> params) {
        if (params == null) {
            return url;
        }
        StringBuilder builder = new StringBuilder(url);
        if (url.contains("?")) {
            builder.append("&");
        } else {
            builder.append("?");
        }
        int i = 0;
        for (String key : params.keySet()) {
            String value = params.get(key);
            // 过滤空的key
            if (value == null) {
                continue;
            }
            if (i != 0) {
                builder.append('&');
            }
            builder.append(key);
            builder.append('=');
            builder.append(encode(value));
            i++;
        }
        return builder.toString();
    }

    public static CloseableHttpClient getHttpsClient() {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            // 初始化SSL上下文
            sslContext.init(null, new TrustManager[]{tm}, null);
            // SSL套接字连接工厂,NoopHostnameVerifier为信任所有服务器
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
            httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return httpclient;
    }

    public static String encode(String input) {
        if (input == null) {
            return "";
        }
        try {
            return URLEncoder.encode(input, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return input;
    }

    public static String post(String url, String certPassword, Map<String, String> param, String xmlParam, boolean isHttps) throws IOException {
        HttpPost http = new HttpPost(url);
        setEntity(http, param, xmlParam);
        return execute(http, certPassword, isHttps);
    }

    /**
     * set post,put,get param
     */
    private static void setEntity(HttpEntityEnclosingRequestBase http, Map<String, String> param, String xmlParam) {
        if (param != null) {
            List<NameValuePair> nvps = new LinkedList<NameValuePair>();
            for (String key : param.keySet())
                nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数
            http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数
        }
        if (xmlParam != null) {
            http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
        }
    }

    //证书密码 微信商户号（mch_id）
    private static String execute(HttpUriRequest http, String certPassword, boolean isHttps) throws ClientProtocolException,
            IOException {
        CloseableHttpClient httpClient = null;
        try {
            if (isHttps) {
                if (isCert) {
                    //TODO 需要完善
                    FileInputStream inputStream = new FileInputStream(new File("证书地址"));
                    KeyStore keystore = KeyStore.getInstance("PKCS12");
                    char[] partnerId2charArray = certPassword.toCharArray();
                    keystore.load(inputStream, partnerId2charArray);
                    SSLContext sslContext = SSLContexts.custom().loadKeyMaterial(keystore, partnerId2charArray).build();
                    SSLConnectionSocketFactory sslsf =
                            new SSLConnectionSocketFactory(sslContext,
                                    new String[]{"TLSv1"},
                                    null,
                                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
                    httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
                } else {
                    SSLContext sslContext = new SSLContextBuilder()
                            .loadTrustMaterial(null, new TrustStrategy() {
                                // 信任所有
                                public boolean isTrusted(X509Certificate[] chain,
                                                         String authType)
                                        throws CertificateException {
                                    return true;
                                }
                            }).build();
                    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                            sslContext);
                    httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
                            .build();
                }
            } else {
                httpClient = HttpClients.createDefault();
            }
            CloseableHttpResponse response = httpClient.execute(http);
            try {
                if (response != null) {
                    if (response.getStatusLine() != null) {
                        int statusCode = response.getStatusLine().getStatusCode();
                        log.info("statusCode:{}", statusCode);
                    }
                    HttpEntity entity = response.getEntity();
                    // 响应内容
                    return EntityUtils.toString(entity, Consts.UTF_8);
                }
            } finally {
                response.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            httpClient.close();
        }
        return null;
    }

}
